/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package logica;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import util.datatypes.DTCliente;
import util.datatypes.DTEntrada;
import util.datatypes.DTFuncion;
import util.datatypes.DTPelicula;
import util.datatypes.DTReserva;
import util.datatypes.DTTiposEntrada;
import util.datatypes.DTVenta;

/**
 *
 * @author bruno
 */
import util.exceptions.NoExisteClienteException;
import util.exceptions.NoExistePeliculaException;
import util.exceptions.NoExisteReservaException;
import util.exceptions.NoExisteVentaException;
import java.util.*;
import persistencia.IPersistenciaAdmin;
import persistencia.IPersistenciaBoleteria;
import persistencia.IPersistenciaKiosco;

public final class Sistema implements IBoleteria, IKiosco, IAdministracion {

    private static Sistema instance = null;
    private List<Cliente> listaClientes;
    private List<DTCliente> listaDTClientes;
    private List<Pelicula> listaPeliculas;
    private List<Venta> listaVentas;
    private TiposEntrada tipoEntradaMenor;
    private TiposEntrada tipoEntradaMayor;
    private TiposEntrada tipoEntradaComun;
    private Calendar calendario = Calendar.getInstance();
    private SimpleDateFormat simpleDateformat = new SimpleDateFormat("yyyy");
    //private int inicioPeliculas = 0;

    public static Sistema getInstance() {
        if (instance == null) {
            instance = new Sistema();
        }
        return instance;
    }

    public Sistema() {
        try {
            /*Inicializo las listas*/
            this.listaPeliculas = new LinkedList<Pelicula>();
            this.listaClientes = new LinkedList<Cliente>();
            this.listaVentas = new LinkedList<Venta>();
            
        } catch (Exception ex) {
            Logger.getLogger(Sistema.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public int guardarFuncionesNuevas() {

        IPersistenciaAdmin iAdmin = persistencia.Fabrica.getPersistenciaAdmin();

        //recorre todas las peliculas viendo para c/u si tiene funciones nuevas
        for (int i = 0; i < listaPeliculas.size(); i++) {
            try {
                Pelicula p = (Pelicula) listaPeliculas.get(i);

                int inicioFunciones = iAdmin.obtenerCantidadFuncionesDePelicula(p.getId());
                int finalFunciones = p.obtenerDTFunciones().size();

                //si la pelicula tiene funciones nuevas estas se guardan
                if (inicioFunciones < finalFunciones) {

                    for (int j = inicioFunciones; j < finalFunciones; j++) {

                        DTFuncion dtf= p.obtenerDTFunciones().get(j);

                        iAdmin.guardarFuncion(dtf, p.getId());
                    }                    
                }

            } catch (Exception ex) {
                Logger.getLogger(Sistema.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return 1;
    }

    public List<DTPelicula> obtenerPeliculasNuevas() {

        List<DTPelicula> cambiosPeliculas = new LinkedList<DTPelicula>();
        try {

            IPersistenciaAdmin iAdmin = persistencia.Fabrica.getPersistenciaAdmin();
            int inicioPeliculas = iAdmin.obtenerCantidadPeliculas();
            if (inicioPeliculas < listaPeliculas.size()) {
                for (int i = inicioPeliculas; i < listaPeliculas.size(); i++) {
                    DTPelicula dtp = ((Pelicula) listaPeliculas.get(i)).getPelicula();
                    cambiosPeliculas.add(dtp);
                }
            }

        } catch (SQLException ex) {
            Logger.getLogger(Sistema.class.getName()).log(Level.SEVERE, null, ex);
        }
        return cambiosPeliculas;
    }
    public List<DTCliente> obtenerClientesNuevos() {

        List<DTCliente> cambiosClientes = new LinkedList<DTCliente>();
        try {

            IPersistenciaAdmin iAdmin = persistencia.Fabrica.getPersistenciaAdmin();
            int inicioClientes = iAdmin.obtenerCantidadClientes();
            if (inicioClientes < listaClientes.size()) {
                for (int i = inicioClientes; i < listaClientes.size(); i++) {
                    DTCliente dtc = ((Cliente) listaClientes.get(i)).getDTCliente();
                    cambiosClientes.add(dtc);
                }
            }

        } catch (SQLException ex) {
            Logger.getLogger(Sistema.class.getName()).log(Level.SEVERE, null, ex);
        }
        return cambiosClientes;
    }

    public int guardarAdministracion() throws Exception {

        int resultado = 0;
        try {
            IPersistenciaAdmin iAdmin = persistencia.Fabrica.getPersistenciaAdmin();
                        
            /* si hubo cambios */
            List<DTCliente> cambiosClientes = obtenerClientesNuevos();
            resultado= iAdmin.guardarClientes(cambiosClientes);

            List<DTPelicula> cambiosPeliculas = obtenerPeliculasNuevas();
            resultado+= iAdmin.guardarPeliculas(cambiosPeliculas);

            resultado+= guardarFuncionesNuevas();


        } catch (Exception e) {
            throw e;
        }
        return resultado;
    }

    private void cargarPeliculas(){

        try {
            IPersistenciaAdmin iAdmin = persistencia.Fabrica.getPersistenciaAdmin();

            List<DTPelicula> peliculas = iAdmin.listarPeliculas();
            for (DTPelicula dt : peliculas) {

                Pelicula p = new Pelicula(dt.getId(), dt.getNombre());
                List<DTFuncion> funciones = iAdmin.listarFuncionesDePelicula(dt.getId());
                for (DTFuncion dtf : funciones) {
                    p.agregarFuncion(new Funcion(dtf.getId(), dtf.getHoraInicio(), dtf.getHoraFin(), dtf.getEntradasDisponibles()));
                }


                this.listaPeliculas.add(p);
            }

        } catch (Exception e) {
            e.getMessage();
        }
    }
    private void cargarClientes(){

        try {
            IPersistenciaAdmin iAdmin = persistencia.Fabrica.getPersistenciaAdmin();

            List<DTCliente> clientes = iAdmin.listarClientes();
            for (DTCliente dt : clientes) {

                Cliente c = new Cliente(dt.getCi(), dt.getNombre(), dt.getFechaNacimiento());

                this.listaClientes.add(c);
            }

        } catch (Exception e) {
            e.getMessage();
        }
    }

    public void CargarDatosAdministracion(){

        cargarPeliculas();
        cargarClientes();
    }

    // <editor-fold defaultstate="collapsed" desc="Cargar Datos En Memoria desde BD Kiosco">

    public void CargarDatosKiosco(){

        getDBTiposEntradas();
        cargarPeliculas();
        getDBClientes();

    }
    // </editor-fold>


    // <editor-fold defaultstate="collapsed" desc="Cargar Datos En Memoria desde BD BOLETERIA">
    public void CargarDatosBoleteria() {
        cargarPeliculas();
        getDBTiposEntradas();
        getDBClientes();
        getDBVentas();
    }

    private void getDBVentas()
    {
        try 
        {
            List<DTVenta> ventas = new LinkedList<DTVenta>();
            IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
            ventas = i.getVentas();
            for (DTVenta v : ventas) {
                Reserva r = new Reserva(v.getReserva().getId(), v.getReserva().getFecha(), v.getReserva().getCostoTotal(),
                        v.getReserva().isEstado(), v.getReserva().isVendida(), new Funcion(v.getReserva().getFuncion().getId(), v.getReserva().getFuncion().getHoraInicio(),
                        v.getReserva().getFuncion().getHoraFin(), v.getReserva().getFuncion().getEntradasDisponibles()), v.getReserva().getTiposEntradas());
                this.listaVentas.add(new Venta(v.getId(), v.getValorAbonado(), r));
            }
            for (Venta v : listaVentas) {
                v.setListaEntradas(getDBEntradas(v.getId()));
            }
        } catch (Exception ex) {
            ex.getMessage();
        }
    }

    private void getDBTiposEntradas() {
        try {
            List<DTTiposEntrada> tipos = new LinkedList<DTTiposEntrada>();
            IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
            tipos = i.getTiposEntradas();
            for(DTTiposEntrada te: tipos)
            {
                if (te.getId() == 1)
                    tipoEntradaMenor = new TiposEntrada(te.getId(), te.getCantidadEntradas(), te.getNombreTipo(), te.getPrecioTipo());
                else if (te.getId() == 3)
                    tipoEntradaMayor = new TiposEntrada(te.getId(), te.getCantidadEntradas(), te.getNombreTipo(), te.getPrecioTipo());
                else if (te.getId() == 2)
                    tipoEntradaComun = new TiposEntrada(te.getId(), te.getCantidadEntradas(), te.getNombreTipo(), te.getPrecioTipo());
            }
        } 
        catch (Exception ex) 
        {
            ex.getMessage();
        }
    }

    private List<Entrada> getDBEntradas(int idVenta) {
        List<Entrada> listaEntradas = new LinkedList<Entrada>();
        try 
        {
            IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
            List<DTEntrada> listaDTEntrada = i.getEntradas(idVenta);
            for (DTEntrada entrada: listaDTEntrada)
                listaEntradas.add(new Entrada(entrada.getId(), 
                        new TiposEntrada(1, entrada.getTipo().getNombreTipo(), entrada.getTipo().getPrecioTipo()), 
                        entrada.getFecha()));
        }
        catch (Exception ex) 
        {
            ex.getMessage();
        }
        return listaEntradas;
    }
    
    private void getDBClientes ()
    {
        try
        {
            IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();

            listaDTClientes = i.listarClientes();

            for (DTCliente c: listaDTClientes)
            {
                listaClientes.add(new Cliente(c.getCi(), c.getNombre(), c.getFechaNacimiento()));
            }

            for (Cliente c: listaClientes)
            {
                c.setListaReservas(getDBListaReservas(c.getCi()));
            }
        }
        catch (Exception ex) 
        {
            ex.getMessage();
        }
     }    
     private List<Reserva> getDBListaReservas(int ciCliente)
     {
         List<Reserva> listaReservas = new LinkedList<Reserva>();
            IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
            List<DTReserva> listaDTReserva = i.listarReservas(ciCliente);
            for (DTReserva dtReserva : listaDTReserva) 
            {
                if(!dtReserva.isEstado() && !dtReserva.isVendida() && !chequearReservaEnHora(dtReserva))
                {
                try
                {
                    cancelarReservaCliente(dtReserva, ciCliente);
                    dtReserva.setEstado(true);
                }
                 catch (NoExisteClienteException ex)
                {
                    ex.getMessage();
                }
                catch (NoExisteReservaException ex)
                {
                    ex.getMessage();
                }
                }
                listaReservas.add(new Reserva(dtReserva.getId(), dtReserva.getFecha(), dtReserva.getCostoTotal(), dtReserva.isEstado(), dtReserva.isVendida(), 
                new Funcion(dtReserva.getFuncion().getId(), dtReserva.getFuncion().getHoraInicio(), dtReserva.getFuncion().getHoraFin(),
                dtReserva.getFuncion().getEntradasDisponibles()), dtReserva.getTiposEntradas()));
            }
        return listaReservas;
     }

    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Datos de Prueba">  
    /*private void cargarDatosFuncion(Pelicula p, double horaInicio, double horaFin) {
        try {
            DTFuncion funcion = new DTFuncion(p.obtenerDTFunciones().size(), horaInicio, horaFin, 15);
            int r = crearFuncion(funcion, p.getId());
        } catch (NoExistePeliculaException ex) {
        }
    }

    private void cargarDatosPruebaReserva(int ci) {
        try {
            List<DTTiposEntrada> lista = new LinkedList<DTTiposEntrada>();
            DTTiposEntrada menor = new DTTiposEntrada(tipoEntradaMenor.getCantidadEntradas(), tipoEntradaMenor.getNombreTipo(), tipoEntradaMenor.getPrecioTipo());
            menor.setCantidadEntradas(2);
            lista.add(menor);
            DTTiposEntrada mayor = new DTTiposEntrada(tipoEntradaMayor.getCantidadEntradas(), tipoEntradaMayor.getNombreTipo(), tipoEntradaMayor.getPrecioTipo());
            mayor.setCantidadEntradas(2);
            lista.add(mayor);
            DTTiposEntrada comun = new DTTiposEntrada(tipoEntradaComun.getCantidadEntradas(), tipoEntradaComun.getNombreTipo(), tipoEntradaComun.getPrecioTipo());
            comun.setCantidadEntradas(1);
            lista.add(comun);
            List<DTFuncion> f = listarFunciones(listaPeliculas.get(0).getId());
            SimpleDateFormat fecha = new SimpleDateFormat("dd/MM/yyyy hh:mm");
            //DTReserva reserva = new DTReserva(1, fecha.parse("17/06/2011 16:55"), 500, false, false, f.get(0), lista);
            //agregarReservaCliente(reserva, ci);
        } catch (Exception ex) {
            ex.getMessage();
        }
    }*/
    // </editor-fold> 

    // <editor-fold defaultstate="collapsed" desc="Métodos Cliente"> 
    public DTCliente buscarCliente(int ciCliente) throws NoExisteClienteException {
        for (Cliente c : listaClientes) {
            if (c.getCi() == ciCliente) {
                return (new DTCliente(c.getCi(), c.getNombre(), c.getFechaNacimiento()));
            }
        }
        throw new NoExisteClienteException();
    }

    public List<DTCliente> listarClientes() {
        listaDTClientes = new LinkedList<DTCliente>();

        for (Cliente c : listaClientes) {
            listaDTClientes.add(c.getDTCliente());
        }
        return listaDTClientes;
    }

    public int crearCliente(DTCliente c) {
        int retorno = 0;
        Cliente cliente = new Cliente(c.getCi(), c.getNombre(), c.getFechaNacimiento());
        try {
            for (Cliente unCliente : listaClientes) {

                if (unCliente.getCi() == c.getCi()) {
                    return -1;
                }
            }
            listaClientes.add(cliente);
            retorno = 1;
        } catch (Exception ex) {

            retorno= -2;
        }
        return retorno;
    }

    public boolean validarCliente(int ciCliente) {

        for (Cliente c : listaClientes) {

            int anioActual = Integer.parseInt(calendario.get(Calendar.YEAR) + "");
            int anioCliente = Integer.parseInt(simpleDateformat.format(c.getFechaNacimiento()));

            if (c.getCi() == ciCliente) {

                if ((anioActual - anioCliente) < 12) {

                    return false;

                }

                return true;

            }

        }
        return false;
    }
    // </editor-fold>
    
    // <editor-fold defaultstate="collapsed" desc="Métodos Reserva">
    public int agregarReservaCliente(DTReserva r, int ciCliente) throws NoExisteClienteException, SQLException {

        try {

            Funcion funcion = new Funcion(r.getFuncion().getId(), r.getFuncion().getHoraInicio(), r.getFuncion().getHoraFin(), r.getFuncion().getEntradasDisponibles());

            Reserva reserva = new Reserva(r.getId(), r.getFecha(), r.getCostoTotal(), r.isEstado(), r.isVendida(), funcion, r.getTiposEntradas());

            for (Cliente c : listaClientes) {
                if (c.getCi() == ciCliente) {

                    persistencia.IPersistenciaKiosco i = persistencia.Fabrica.getPersistenciaKiosco();

                    i.agregarReserva(ciCliente, r);

                    return c.crearReserva(reserva);
                }
            }

        } catch (SQLException e) {
        }

        throw new NoExisteClienteException();
    }

    public int cancelarReservaCliente(DTReserva r, int ciCliente) throws NoExisteClienteException, NoExisteReservaException 
    {
        int result = 0;
        try 
        {
            for (Cliente c : listaClientes) 
            {
                if (c.getCi() == ciCliente) 
                {
                    IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
                    i.cancelarReserva(r.getId());
                    result = c.cancelarReserva(r.getId());
                }
            }
        } catch (NoExisteReservaException ex) {
            ex.getMessage();
        } catch (Exception ex) {
            ex.getMessage();
        }
        return result;
    }

    public int modificarReservaCliente(DTReserva r, int ciCliente) throws NoExisteReservaException {
        try
        {
            for (Cliente c : listaClientes) 
            {
                if (c.getCi() == ciCliente) 
                {
                    Funcion f = new Funcion(r.getFuncion().getId(), r.getFuncion().getHoraInicio(), r.getFuncion().getHoraFin(), r.getFuncion().getEntradasDisponibles());
                    Reserva reserva = new Reserva(r.getId(), r.getFecha(), r.getCostoTotal(), r.isEstado(), r.isVendida(), f, r.getTiposEntradas());
                    IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
                    i.modificarReserva(r);
                    return c.modificarReserva(reserva);
                }
            }
        }
        catch(NoExisteReservaException ex)
        {
            ex.getMessage();
        }
        return 0;
    }

    public boolean chequearFuncionesSolapadas(DTFuncion func, int ciCliente) throws NoExisteClienteException {
        Funcion f = new Funcion(func.getId(), func.getHoraInicio(), func.getHoraFin(), func.getEntradasDisponibles());

        for (Cliente c : listaClientes) {
            if (c.getCi() == ciCliente) {
                return c.chequearFuncionesSolapadas(f);
            }
        }
        throw new NoExisteClienteException();
    }

    public List<DTReserva> listarReservas(int ciCliente) throws NoExisteClienteException {
        for (Cliente c : listaClientes) 
        {
            if (c.getCi() == ciCliente) 
            {
                return c.getDTReservas();
            }
        }

        throw new NoExisteClienteException();
    }

    public boolean chequearReservaEnHora(DTReserva r) 
    {
        Calendar actual = Calendar.getInstance();
        actual.add(Calendar.MINUTE, -45);
        Date actualDate = actual.getTime();
        if (actualDate.compareTo(r.getFecha()) < 0) 
        {
            return true;
        }
        return false;
    }
    // </editor-fold>   

    // <editor-fold defaultstate="collapsed" desc="Métodos Pelicula">
    public int crearPelicula(DTPelicula p) {
        Pelicula pelicula = new Pelicula(listaPeliculas.size() + 1, p.getNombre());
        try {
            listaPeliculas.add(pelicula);
            return 1;
        } catch (Exception ex) {
            ex.toString();
        }
        return 0;
    }

    public DTPelicula getPelicula(int id) {
        for (Pelicula p : listaPeliculas) {
            if (p.getId() == id) {
                return new DTPelicula(p.getId(), p.getNombre());
            }
        }
        return null;
    }

    public List<DTPelicula> listarPeliculas() {
        List<DTPelicula> dtListPeliculas = new LinkedList<DTPelicula>();
        for (Pelicula p : listaPeliculas) {
            dtListPeliculas.add(p.getPelicula());
        }
        return dtListPeliculas;
    }

    public int crearFuncion(DTFuncion f, int idPelicula) throws NoExistePeliculaException {
        
        Funcion funcion = new Funcion(f.getId(), f.getHoraInicio(), f.getHoraFin(), f.getEntradasDisponibles());
        for (Pelicula p : listaPeliculas) {
            if (p.getId() == idPelicula) {
                return p.agregarFuncion(funcion);
            }
        }
        throw new NoExistePeliculaException();
    }

    public Double obtenerHoraDouble(String horaString) {

        String resto_min = horaString.substring(horaString.lastIndexOf(":") + 1, horaString.length());
        String resto_hora = horaString.substring(0, horaString.lastIndexOf(":"));

        return Double.valueOf(resto_hora).doubleValue() + (Double.valueOf(resto_min).doubleValue() / 60);

    }

    public String obtenerHoraString(Double horaDouble) {

        String horaString = "" + horaDouble;
        String resto_decimal = horaString.substring(horaString.lastIndexOf("."), horaString.length());
        String hora = horaString.substring(0, horaString.lastIndexOf("."));
        int min = (int) Math.floor(Double.valueOf(resto_decimal).doubleValue() * 60);

        if (hora.length() < 2) {
            hora = "0" + hora;
        }

        return hora + ":" + min;

    }

    public List<DTFuncion> listarFunciones(int idPelicula) throws NoExistePeliculaException {
        List<DTFuncion> funciones = new LinkedList<DTFuncion>();
        for (Pelicula pel : listaPeliculas) {
            if (pel.getId() == idPelicula) {
                funciones = pel.obtenerDTFunciones();
            }
        }
        return funciones;
    }

    public DTFuncion getFuncionById(int idFuncion, int idPelicula) throws NoExistePeliculaException {
        List<DTFuncion> funciones = listarFunciones(idPelicula);
        for (DTFuncion f : funciones) {
            if (f.getId() == idFuncion) {
                return f;
            }
        }
        throw new NoExistePeliculaException();
    }

    public DTPelicula getFuncionPelicula(DTFuncion f) {
        List<DTFuncion> funciones;
        for (Pelicula p : listaPeliculas) {
            funciones = new LinkedList<DTFuncion>();
            funciones = p.obtenerDTFunciones();
            for (DTFuncion fu : funciones) {
                if (fu.getId() == f.getId()) {
                    return (new DTPelicula(p.getId(), p.getNombre()));
                }
            }
        }
        return null;
    }

    public boolean getChequearHoraFuncion(DTFuncion funcion) {

        String hora = calendario.get(Calendar.HOUR_OF_DAY) + ":" + calendario.get(Calendar.MINUTE);
        double horaInicio = funcion.getHoraInicio();
        double horaActual = obtenerHoraDouble(hora);
        horaActual = horaActual + 0.50;

        double resto_entero = Math.floor((horaActual));
        double resto = horaActual - resto_entero;

        if (horaActual >= 24) {

            horaActual = resto;
        }

        if (horaInicio <= 1) {
            
            horaInicio = funcion.getHoraInicio() + 24;
        }
        if (horaActual <= horaInicio) {

            return true;
        }

        return false;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Métodos TipoEntrada">
    public DTTiposEntrada getTipoMenor() {
        return (new DTTiposEntrada(tipoEntradaMenor.getId(), tipoEntradaMenor.getCantidadEntradas(), tipoEntradaMenor.getNombreTipo(), tipoEntradaMenor.getPrecioTipo()));
    }

    public DTTiposEntrada getTipoMayor() {
        return (new DTTiposEntrada(tipoEntradaMayor.getId(), tipoEntradaMayor.getCantidadEntradas(), tipoEntradaMayor.getNombreTipo(), tipoEntradaMayor.getPrecioTipo()));
    }

    public DTTiposEntrada getTipoComun() {
        return (new DTTiposEntrada(tipoEntradaComun.getId(), tipoEntradaComun.getCantidadEntradas(), tipoEntradaComun.getNombreTipo(), tipoEntradaComun.getPrecioTipo()));
    }

    public boolean typeOfTipoMenor(DTTiposEntrada entrada) {
        if (entrada.getId() == tipoEntradaMenor.getId()) {
            return true;
        }
        return false;
    }

    public boolean typeOfTipoMayor(DTTiposEntrada entrada) {
        if (entrada.getId() == tipoEntradaMayor.getId()) {
            return true;
        }
        return false;
    }

    public boolean typeOfTipoComun(DTTiposEntrada entrada) {
        if (entrada.getId() == tipoEntradaComun.getId()) {
            return true;
        }
        return false;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Métodos Venta">
    public int crearVenta(DTVenta v) {
        try {
            IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
            i.almacenarVentas(v);
            Funcion funcion = new Funcion(v.getReserva().getFuncion().getId(), v.getReserva().getFuncion().getHoraInicio(),
                    v.getReserva().getFuncion().getHoraFin(), v.getReserva().getFuncion().getEntradasDisponibles());
            Reserva reserva = new Reserva(v.getReserva().getId(), v.getReserva().getFecha(),
                    v.getReserva().getCostoTotal(), v.getReserva().isEstado(), v.getReserva().isVendida(), funcion, v.getReserva().getTiposEntradas());
            Venta venta = new Venta(listaVentas.size() + 1, v.getValorAbonado(), reserva);
            listaVentas.add(venta);
            return venta.getId();
        } catch (Exception ex) {
            ex.getMessage();
        }
        return 0;
    }

    public int crearEntrada(List<DTEntrada> entradas, int idVenta) throws NoExisteVentaException {
        int ups = 0;
        try {
            for (Venta venta : listaVentas) 
            {
                if (venta.getId() == idVenta) 
                {
                    IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
                    i.almacenarEntradas(entradas, idVenta);
                    for (DTEntrada e : entradas) 
                    {
                        Entrada entrada = new Entrada(e.getId(), (new TiposEntrada(e.getTipo().getId(), e.getTipo().getCantidadEntradas(), e.getTipo().getNombreTipo(), e.getTipo().getPrecioTipo())),
                                e.getFecha());
                        entrada.setFuncion(venta.getReserva().getFuncion());
                        ups += venta.generarEntrada(entrada);
                    }
                    venderReserva(venta.getReserva().getId());
                    disminuirEntradasFuncion(venta.getReserva().getFuncion().getId(), entradas.size());
                }
            }
            throw new NoExisteVentaException();
        } catch (Exception ex) {
            ex.toString();
        }
        return ups;
    }
    // </editor-fold>
    
    private void venderReserva (int idReserva)
    {
        try 
        {
            IPersistenciaBoleteria i = persistencia.Fabrica.getPersistenciaBoleteria();
            i.venderReserva(idReserva);
            for (Cliente c: listaClientes) 
            {
                for (Reserva r: c.getListaReservas())
                    if (r.getId() == idReserva)
                    {
                        r.setVendida(true);
                    }
            }
        } 
        catch (Exception ex) 
        {
            ex.toString();
        }
    }
    
    private void disminuirEntradasFuncion(int idFuncion, int cantEntradas)
    {
        for(Pelicula p: listaPeliculas)
        {
            for (Funcion f: p.getListaFunciones())
            {
                if (f.getId() == idFuncion)
                    f.setEntradasDisponibles(f.getEntradasDisponibles() - cantEntradas);
            }
        }
    }
    
    public int contarEntradas(DTFuncion f)
    {
        Calendar desdeFecha = Calendar.getInstance();
        Calendar hastaFecha = Calendar.getInstance();
        String hora = calendario.get(Calendar.HOUR_OF_DAY) + ":" + calendario.get(Calendar.MINUTE);
        double horaActual = obtenerHoraDouble(hora);
        if (horaActual < f.getHoraInicio())
        {
            desdeFecha.add(Calendar.DATE, -1);
            desdeFecha.set(Calendar.HOUR_OF_DAY, (int)(f.getHoraInicio() - (f.getHoraInicio() - Math.floor(f.getHoraInicio()))));
            desdeFecha.set(Calendar.MINUTE, (int)(Math.floor(f.getHoraInicio())) + 1);
        }
        else 
        {
            hastaFecha.add(Calendar.DATE, 1);
            hastaFecha.set(Calendar.HOUR_OF_DAY, (int)(horaActual - Math.floor(horaActual)));
            hastaFecha.set(Calendar.MINUTE, (int)(Math.floor(horaActual))-30);
        }
        IPersistenciaKiosco i = persistencia.Fabrica.getPersistenciaKiosco();
        int cantidadEntradas = i.getCantidadEntradasVendidas(desdeFecha, hastaFecha, f.getId());
        return f.getEntradasDisponibles() - cantidadEntradas;
    }
}
